#ifndef _CG_H_
#define _CG_H_

#define X 0
#define Y 1
#define Z 2

typedef struct _cgPoint
{
    double c[3];
} cgPoint;

typedef struct _cgPoint4
{
    double c[4];
} cgPoint4;

typedef struct _cgLine
{
    cgPoint p[2];
} cgLine;

typedef struct _cgTriangle
{
    cgPoint p[3];
} cgTriangle;

typedef double TransformMatrix[4][4];

void cg_point4_from_point3(cgPoint4 *p4, cgPoint *p3);
void cg_point3_from_point4(cgPoint *p3, cgPoint4 *p4);

TransformMatrix *cg_identity_matrix(TransformMatrix *tm);

TransformMatrix *cg_rot_matrix_x(double angle, TransformMatrix *tm);
TransformMatrix *cg_rot_matrix_y(double angle, TransformMatrix *tm);
TransformMatrix *cg_rot_matrix_z(double angle, TransformMatrix *tm);
TransformMatrix *cg_translate_matrix(
    double x,
    double y,
    double z,
    TransformMatrix *tm);
TransformMatrix *cg_zoom_matrix(
    double x,
    double y,
    double z,
    TransformMatrix *tm);

void cg_mult_matrix(TransformMatrix *tm1, TransformMatrix *tm2);

void cg_rotate(TransformMatrix *tm, int axis, double angle);
void cg_translate(TransformMatrix *tm, double x, double y, double z);
void cg_zoom(TransformMatrix *tm, double x, double y, double z);
void cg_matrix_to_opengl(double *otm, TransformMatrix *tm);

void cg_transform_point(cgPoint *dest, cgPoint *src, TransformMatrix *tm);
void cg_transform_points(cgPoint *buf, int size, TransformMatrix *tm);
void cg_transform_lines(cgLine *buf, int size, TransformMatrix *tm);
void cg_transform_triangles(cgTriangle *buf, int size, TransformMatrix *tm);
void cg_transform_grid(cgPoint **buf, int w, int h, TransformMatrix *tm);

#endif  // _CG_H_
